{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# coding = utf-8\n",
    "\"\"\"\n",
    "Created on Tue May  1 20:43:28 2018\n",
    "@author: eesungkim\n",
    "\"\"\"\n",
    "\n",
    "import os\n",
    "import math\n",
    "import numpy as np\n",
    "import scipy.io.wavfile as wav\n",
    "import matplotlib.pyplot as plt\n",
    "from numpy.linalg import norm\n",
    "from scipy.special import jv\n",
    "\n",
    "def bessel(v, X):\n",
    "    return ((1j ** (-v)) * jv(v, 1j * X)).real\n",
    "\n",
    "\n",
    "def stft(x, n_fft=512, win_length=400, hop_length=160, window='hamming'):\n",
    "    if window == 'hanning':\n",
    "        window = np.hanning(win_length)\n",
    "    elif window == 'hamming':\n",
    "        window = np.hamming(win_length)\n",
    "    elif window == 'rectangle':\n",
    "        window = np.ones(win_length)\n",
    "    return np.array(\n",
    "        [np.fft.rfft(window * x[i:i + win_length], n_fft, axis=0) for i in range(0, len(x) - win_length, hop_length)])\n",
    "\n",
    "\n",
    "def estnoisem(pSpectrum, hop_length):\n",
    "    (nFrames, nFFT2) = np.shape(pSpectrum)  # number of frames and freq bins\n",
    "    x = np.array(np.zeros((nFrames, nFFT2)))  # initialize output arrays\n",
    "    xs = np.array(np.zeros((nFrames, nFFT2)))  # will hold std error in the future\n",
    "\n",
    "    # default algorithm constants\n",
    "    taca = 0.0449  # smoothing time constant for alpha_c = -hop_length/log(0.7) in equ (11)\n",
    "    tamax = 0.392  # max smoothing time constant in (3) = -hop_length/log(0.96)\n",
    "    taminh = 0.0133  # min smoothing time constant (upper limit) in (3) = -hop_length/log(0.3)\n",
    "    tpfall = 0.064  # time constant for P to fall (12)\n",
    "    tbmax = 0.0717  # max smoothing time constant in (20) = -hop_length/log(0.8)\n",
    "    qeqmin = 2.0  # minimum value of Qeq (23)\n",
    "    qeqmax = 14.0  # max value of Qeq per frame\n",
    "    av = 2.12  # fudge factor for bc calculation (23 + 13 lines)\n",
    "    td = 1.536  # time to take minimum over\n",
    "    nu = 8  # number of subwindows\n",
    "    qith = np.array([0.03, 0.05, 0.06, np.Inf], dtype=float)  # noise slope thresholds in dB/s\n",
    "    nsmdb = np.array([47, 31.4, 15.7, 4.1], dtype=float)  # maximum permitted +ve noise slope in dB/s\n",
    "\n",
    "    # derived algorithm constants\n",
    "    aca = np.exp(-hop_length / taca)  # smoothing constant for alpha_c in equ (11) = 0.7\n",
    "    acmax = aca  # min value of alpha_c = 0.7 in equ (11) also = 0.7\n",
    "    amax = np.exp(-hop_length / tamax)  # max smoothing constant in (3) = 0.96\n",
    "    aminh = np.exp(-hop_length / taminh)  # min smoothing constant (upper limit) in (3) = 0.3\n",
    "    bmax = np.exp(-hop_length / tbmax)  # max smoothing constant in (20) = 0.8\n",
    "    SNRexp = -hop_length / tpfall\n",
    "    nv = round(td / (hop_length * nu))  # length of each subwindow in frames\n",
    "\n",
    "    if nv < 4:  # algorithm doesn't work for miniscule frames\n",
    "        nv = 4\n",
    "        nu = round(td / (hop_length * nv))\n",
    "    nd = nu * nv  # length of total window in frames\n",
    "    (md, hd, dd) = mhvals(nd)  # calculate the constants M(D) and H(D) from Table III\n",
    "    (mv, hv, dv) = mhvals(nv)  # calculate the constants M(D) and H(D) from Table III\n",
    "    nsms = np.array([10]) ** (nsmdb * nv * hop_length / 10)  # [8 4 2 1.2] in paper\n",
    "    qeqimax = 1 / qeqmin  # maximum value of Qeq inverse (23)\n",
    "    qeqimin = 1 / qeqmax  # minumum value of Qeq per frame inverse\n",
    "\n",
    "    p = pSpectrum[0, :]  # smoothed power spectrum\n",
    "    ac = 1  # correction factor (9)\n",
    "    sn2 = p  # estimated noise power\n",
    "    pb = p  # smoothed noisy speech power (20)\n",
    "    pb2 = pb ** 2\n",
    "    pminu = p\n",
    "    actmin = np.array(np.ones(nFFT2) * np.Inf)  # Running minimum estimate\n",
    "    actminsub = np.array(np.ones(nFFT2) * np.Inf)  # sub-window minimum estimate\n",
    "    subwc = nv  # force a buffer switch on first loop\n",
    "    actbuf = np.array(np.ones((nu, nFFT2)) * np.Inf)  # buffer to store subwindow minima\n",
    "    ibuf = 0\n",
    "    lminflag = np.zeros(nFFT2)  # flag to remember local minimum\n",
    "\n",
    "    # loop for each frame\n",
    "    for t in range(0, nFrames):  # we use t instead of lambda in the paper\n",
    "        pSpectrum_t = pSpectrum[t, :]  # noise speech power spectrum\n",
    "        acb = (1 + (sum(p) / sum(pSpectrum_t) - 1) ** 2) ** (-1)  # alpha_c-bar(t)  (9)\n",
    "\n",
    "        tmp = np.array([acb])\n",
    "        tmp[tmp < acmax] = acmax\n",
    "        # max_complex(np.array([acb] ),np.array([acmax] ))\n",
    "        ac = aca * ac + (1 - aca) * tmp  # alpha_c(t)  (10)\n",
    "        ah = amax * ac * (1 + (p / sn2 - 1) ** 2) ** (-1)  # alpha_hat: smoothing factor per frequency (11)\n",
    "        SNR = sum(p) / sum(sn2)\n",
    "        ah = max_complex(ah,\n",
    "                         min_complex(np.array([aminh]), np.array([SNR ** SNRexp])))  # lower limit for alpha_hat (12)\n",
    "        p = ah * p + (1 - ah) * pSpectrum_t  # smoothed noisy speech power (3)\n",
    "        b = min_complex(ah ** 2,\n",
    "                        np.array([bmax]))  # smoothing constant for estimating periodogram variance (22 + 2 lines)\n",
    "        pb = b * pb + (1 - b) * p  # smoothed periodogram (20)\n",
    "        pb2 = b * pb2 + (1 - b) * p ** 2  # smoothed periodogram squared (21)\n",
    "        qeqi = max_complex(min_complex((pb2 - pb ** 2) / (2 * sn2 ** 2), np.array([qeqimax])),\n",
    "                           np.array([qeqimin / (t + 1)]))  # Qeq inverse (23)\n",
    "        qiav = sum(\n",
    "            qeqi) / nFFT2  # Average over all frequencies (23+12 lines) (ignore non-duplication of DC and nyquist terms)\n",
    "        bc = 1 + av * np.sqrt(qiav)  # bias correction factor (23+11 lines)\n",
    "        bmind = 1 + 2 * (nd - 1) * (1 - md) / (\n",
    "                    qeqi ** (-1) - 2 * md)  # we use the signalmplified form (17) instead of (15)\n",
    "        bminv = 1 + 2 * (nv - 1) * (1 - mv) / (qeqi ** (-1) - 2 * mv)  # same expressignalon but for sub windows\n",
    "        kmod = (bc * p * bmind) < actmin  # Frequency mask for new minimum\n",
    "\n",
    "        if any(kmod):\n",
    "            actmin[kmod] = bc * p[kmod] * bmind[kmod]\n",
    "            actminsub[kmod] = bc * p[kmod] * bminv[kmod]\n",
    "\n",
    "        if subwc > 1 and subwc < nv:  # middle of buffer - allow a local minimum\n",
    "            lminflag = np.logical_or(lminflag, kmod)  # potential local minimum frequency bins\n",
    "            pminu = min_complex(actminsub, pminu)\n",
    "            sn2 = pminu.copy()\n",
    "        else:\n",
    "            if subwc >= nv:  # end of buffer - do a buffer switch\n",
    "                ibuf = 1 + (ibuf % nu)  # increment actbuf storage pointer\n",
    "                actbuf[ibuf - 1, :] = actmin.copy()  # save sub-window minimum\n",
    "                pminu = min_complex_mat(actbuf)\n",
    "                i = np.nonzero(np.array(qiav) < qith)\n",
    "                nsm = nsms[i[0][0]]  # noise slope max\n",
    "                lmin = np.logical_and(\n",
    "                    np.logical_and(np.logical_and(lminflag, np.logical_not(kmod)), actminsub < (nsm * pminu)),\n",
    "                    actminsub > pminu)\n",
    "                if any(lmin):\n",
    "                    pminu[lmin] = actminsub[lmin]\n",
    "                    actbuf[:, lmin] = np.ones((nu, 1)) * pminu[lmin]\n",
    "                lminflag[:] = 0\n",
    "                actmin[:] = np.Inf\n",
    "                subwc = 0\n",
    "        subwc = subwc + 1\n",
    "        x[t, :] = sn2.copy()\n",
    "        qisq = np.sqrt(qeqi)\n",
    "        # empirical formula for standard error based on Fig 15 of [2]\n",
    "        xs[t, :] = sn2 * np.sqrt(\n",
    "            0.266 * (nd + 100 * qisq) * qisq / (1 + 0.005 * nd + 6 / nd) / (0.5 * qeqi ** (-1) + nd - 1))\n",
    "\n",
    "    return x\n",
    "\n",
    "\n",
    "def mhvals(*args):\n",
    "    nargin = len(args)\n",
    "\n",
    "    dmh = np.array([\n",
    "        [1, 0, 0],\n",
    "        [2, 0.26, 0.15],\n",
    "        [5, 0.48, 0.48],\n",
    "        [8, 0.58, 0.78],\n",
    "        [10, 0.61, 0.98],\n",
    "        [15, 0.668, 1.55],\n",
    "        [20, 0.705, 2],\n",
    "        [30, 0.762, 2.3],\n",
    "        [40, 0.8, 2.52],\n",
    "        [60, 0.841, 3.1],\n",
    "        [80, 0.865, 3.38],\n",
    "        [120, 0.89, 4.15],\n",
    "        [140, 0.9, 4.35],\n",
    "        [160, 0.91, 4.25],\n",
    "        [180, 0.92, 3.9],\n",
    "        [220, 0.93, 4.1],\n",
    "        [260, 0.935, 4.7],\n",
    "        [300, 0.94, 5]\n",
    "    ], dtype=float)\n",
    "\n",
    "    if nargin >= 1:\n",
    "        d = args[0]\n",
    "        i = np.nonzero(d <= dmh[:, 0])\n",
    "        if len(i) == 0:\n",
    "            i = np.shape(dmh)[0] - 1\n",
    "            j = i\n",
    "        else:\n",
    "            i = i[0][0]\n",
    "            j = i - 1\n",
    "        if d == dmh[i, 0]:\n",
    "            m = dmh[i, 1]\n",
    "            h = dmh[i, 2]\n",
    "        else:\n",
    "            qj = np.sqrt(dmh[i - 1, 0])  # interpolate usignalng sqrt(d)\n",
    "            qi = np.sqrt(dmh[i, 0])\n",
    "            q = np.sqrt(d)\n",
    "            h = dmh[i, 2] + (q - qi) * (dmh[j, 2] - dmh[i, 2]) / (qj - qi)\n",
    "            m = dmh[i, 1] + (qi * qj / q - qj) * (dmh[j, 1] - dmh[i, 1]) / (qi - qj)\n",
    "    else:\n",
    "        d = dmh[:, 0].copy()\n",
    "        m = dmh[:, 1].copy()\n",
    "        h = dmh[:, 2].copy()\n",
    "\n",
    "    return m, h, d\n",
    "\n",
    "\n",
    "def max_complex(a, b):\n",
    "    if len(a) == 1 and len(b) > 1:\n",
    "        a = np.tile(a, np.shape(b))\n",
    "    if len(b) == 1 and len(a) > 1:\n",
    "        b = np.tile(b, np.shape(a))\n",
    "\n",
    "    i = np.logical_or(np.iscomplex(a), np.iscomplex(b))\n",
    "\n",
    "    aa = a.copy()\n",
    "    bb = b.copy()\n",
    "\n",
    "    if any(i):\n",
    "        aa[i] = np.absolute(aa[i])\n",
    "        bb[i] = np.absolute(bb[i])\n",
    "    if a.dtype == 'complex' or b.dtype == 'complex':\n",
    "        cc = np.array(np.zeros(np.shape(a)))\n",
    "    else:\n",
    "        cc = np.array(np.zeros(np.shape(a)), dtype=float)\n",
    "\n",
    "    i = aa > bb\n",
    "    cc[i] = a[i]\n",
    "    cc[np.logical_not(i)] = b[np.logical_not(i)]\n",
    "\n",
    "    return cc\n",
    "\n",
    "\n",
    "def min_complex(a, b):\n",
    "\n",
    "    if len(a) == 1 and len(b) > 1:\n",
    "        a = np.tile(a, np.shape(b))\n",
    "    if len(b) == 1 and len(a) > 1:\n",
    "        b = np.tile(b, np.shape(a))\n",
    "\n",
    "    i = np.logical_or(np.iscomplex(a), np.iscomplex(b))\n",
    "\n",
    "    aa = a.copy()\n",
    "    bb = b.copy()\n",
    "\n",
    "    if any(i):\n",
    "        aa[i] = np.absolute(aa[i])\n",
    "        bb[i] = np.absolute(bb[i])\n",
    "\n",
    "    if a.dtype == 'complex' or b.dtype == 'complex':\n",
    "        cc = np.array(np.zeros(np.shape(a)))\n",
    "    else:\n",
    "        cc = np.array(np.zeros(np.shape(a)), dtype=float)\n",
    "\n",
    "    i = aa < bb\n",
    "    cc[i] = a[i]\n",
    "    cc[np.logical_not(i)] = b[np.logical_not(i)]\n",
    "\n",
    "    return cc\n",
    "\n",
    "\n",
    "def min_complex_mat(a):\n",
    "    s = np.shape(a)\n",
    "    m = np.array(np.zeros(s[1]))\n",
    "    for i in range(0, s[1]):\n",
    "        j = np.argmin(np.absolute(a[:, i]))\n",
    "        m[i] = a[j, i]\n",
    "    return m\n",
    "\n",
    "\n",
    "def VAD(signal, sr, nFFT=512, win_length=0.025, hop_length=0.01, theshold=0.7):\n",
    "    \"\"\"Voice Activity Detector\n",
    "    J. Sohn, N. S. Kim, and W. Sung. \"A statistical model-based voice activity detection,\" IEEE Signal Processing Letters, Vol. 6, issue 1, pp. 1-3, Jan. 1999.\n",
    "    Parameters\n",
    "    ----------\n",
    "    signal      : audio time series\n",
    "    sr    \t\t: sampling rate of `signal`\n",
    "    nFFT     \t: length of the FFT window\n",
    "    win_length \t: window size in sec\n",
    "    hop_length \t: hop size in sec\n",
    "    Returns\n",
    "    -------\n",
    "    probRatio   : frame-based voice activity probability sequence\n",
    "    \"\"\"\n",
    "    signal = signal.astype('float')\n",
    "\n",
    "    maxPosteriorSNR = 100\n",
    "    minPosteriorSNR = 0.0001\n",
    "\n",
    "    win_length_sample = round(win_length * sr)\n",
    "    hop_length_sample = round(hop_length * sr)\n",
    "\n",
    "    # the variance of the speech; lambda_x(k)\n",
    "    _stft = stft(signal, n_fft=nFFT, win_length=win_length_sample, hop_length=hop_length_sample)\n",
    "    pSpectrum = np.abs(_stft) ** 2\n",
    "\n",
    "    # estimate the variance of the noise using minimum statistics noise PSD estimation ; lambda_d(k).\n",
    "    estNoise = estnoisem(pSpectrum, hop_length)\n",
    "    estNoise = estNoise\n",
    "\n",
    "    aPosterioriSNR = pSpectrum / estNoise\n",
    "    aPosterioriSNR = aPosterioriSNR\n",
    "    aPosterioriSNR[aPosterioriSNR > maxPosteriorSNR] = maxPosteriorSNR\n",
    "    aPosterioriSNR[aPosterioriSNR < minPosteriorSNR] = minPosteriorSNR\n",
    "\n",
    "    a01 = hop_length / 0.05  # a01=P(signallence->speech)  hop_length/mean signallence length (50 ms)\n",
    "    a00 = 1 - a01  # a00=P(signallence->signallence)\n",
    "    a10 = hop_length / 0.1  # a10=P(speech->signallence) hop/mean talkspurt length (100 ms)\n",
    "    a11 = 1 - a10  # a11=P(speech->speech)\n",
    "\n",
    "    b01 = a01 / a00\n",
    "    b10 = a11 - a10 * a01 / a00\n",
    "\n",
    "    smoothFactorDD = 0.99\n",
    "    previousGainedaPosSNR = 1\n",
    "    (nFrames, nFFT2) = pSpectrum.shape\n",
    "    probRatio = np.zeros((nFrames, 1))\n",
    "    logGamma_frame = 0\n",
    "    for i in range(nFrames):\n",
    "        aPosterioriSNR_frame = aPosterioriSNR[i, :]\n",
    "\n",
    "        # operator [2](52)\n",
    "        oper = aPosterioriSNR_frame - 1\n",
    "        oper[oper < 0] = 0\n",
    "        smoothed_a_priori_SNR = smoothFactorDD * previousGainedaPosSNR + (1 - smoothFactorDD) * oper\n",
    "\n",
    "        # V for MMSE estimate ([2](8))\n",
    "        V = 0.1 * smoothed_a_priori_SNR * aPosterioriSNR_frame / (1 + smoothed_a_priori_SNR)\n",
    "\n",
    "        # geometric mean of log likelihood ratios for individual frequency band  [1](4)\n",
    "        logLRforFreqBins = 2 * V - np.log(smoothed_a_priori_SNR + 1)\n",
    "        # logLRforFreqBins=np.exp(smoothed_a_priori_SNR*aPosterioriSNR_frame/(1+smoothed_a_priori_SNR))/(1+smoothed_a_priori_SNR)\n",
    "        gMeanLogLRT = np.mean(logLRforFreqBins)\n",
    "        logGamma_frame = np.log(a10 / a01) + gMeanLogLRT + np.log(b01 + b10 / (a10 + a00 * np.exp(-logGamma_frame)))\n",
    "        probRatio[i] = 1 / (1 + np.exp(-logGamma_frame))\n",
    "\n",
    "        # Calculate Gain function which results from the MMSE [2](7).\n",
    "        gain = (math.gamma(1.5) * np.sqrt(V)) / aPosterioriSNR_frame * np.exp(-1 * V / 2) * (\n",
    "                    (1 + V) * bessel(0, V / 2) + V * bessel(1, V / 2))\n",
    "\n",
    "        previousGainedaPosSNR = (gain ** 2) * aPosterioriSNR_frame\n",
    "        probRatio[probRatio > theshold] = 1\n",
    "        probRatio[probRatio < theshold] = 0\n",
    "\n",
    "    arr = []\n",
    "    for idx, frame in enumerate(probRatio):\n",
    "        if idx == 1:\n",
    "            for _ in range(int(sr * (win_length - hop_length))):\n",
    "                arr.append(frame[0])\n",
    "            continue;\n",
    "        for _ in range(int(sr * hop_length)):\n",
    "            arr.append(frame[0])\n",
    "    l = len(signal) - len(arr)\n",
    "    return (arr + [0] * l)[:len(signal)]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/kakao/anaconda3/lib/python3.7/site-packages/mkl_fft/_numpy_fft.py:331: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result.\n",
      "  output = mkl_fft.rfft_numpy(a, n=n, axis=axis)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "path_clean = 'datasets/SI1265_FJWB0_2.wav'\n",
    "\n",
    "path_wav = os.path.join(os.getcwd() , path_clean )\n",
    "(sr, signal) = wav.read(path_wav)\n",
    "\n",
    "vad=VAD(signal, sr, nFFT=512, win_length=0.025, hop_length=0.01, theshold=0.99)\n",
    "\n",
    "plt.subplot(2, 1, 1)\n",
    "plt.plot(signal)\n",
    "plt.title('Time Signal')\n",
    "\n",
    "plt.subplot(2, 1, 2)\n",
    "plt.plot(vad)\n",
    "\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
